using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;
using System.Security;

namespace RuiXinCoffee.Utils
{
    public static class ImageHelper
    {
        //获取图片存储目录的物理路径
        private static string GetImageDirectory()
        {
            try
            {
                //使用项目根目录下的Images文件夹作为图片存储位置
                string baseDir = AppDomain.CurrentDomain.BaseDirectory;
                
                //从bin目录回溯到项目根目录
                string projectDir = baseDir;
                if (baseDir.Contains("\\bin\\"))
                {
                    projectDir = baseDir.Substring(0, baseDir.IndexOf("\\bin\\"));
                }
                
                string imagesDir = Path.Combine(projectDir, "Images");
                if (!Directory.Exists(imagesDir))
                {
                    try
                    {
                        Directory.CreateDirectory(imagesDir);
                        Console.WriteLine($"成功创建图片目录: {imagesDir}");
                    }
                    catch (UnauthorizedAccessException ex)
                    {
                        throw new ImageProcessException($"没有权限创建图片目录: {imagesDir}", ex);
                    }
                    catch (Exception ex)
                    {
                        throw new ImageProcessException($"创建图片目录失败: {imagesDir}", ex);
                    }
                }
                return imagesDir;
            }
            catch (Exception ex)
            {
                throw new ImageProcessException("创建图片存储目录失败", ex);
            }
        }

        //获取轮播图片存储目录的物理路径
        private static string GetCarouselImageDirectory()
        {
            try
            {
                //先获取Images目录
                string imagesDir = GetImageDirectory();
                
                //创建Carousel子目录
                string carouselDir = Path.Combine(imagesDir, "Carousel");
                if (!Directory.Exists(carouselDir))
                {
                    try
                    {
                        Directory.CreateDirectory(carouselDir);
                        Console.WriteLine($"成功创建轮播图片目录: {carouselDir}");
                    }
                    catch (UnauthorizedAccessException ex)
                    {
                        throw new ImageProcessException($"没有权限创建轮播图片目录: {carouselDir}", ex);
                    }
                    catch (Exception ex)
                    {
                        throw new ImageProcessException($"创建轮播图片目录失败: {carouselDir}", ex);
                    }
                }
                return carouselDir;
            }
            catch (Exception ex)
            {
                throw new ImageProcessException("创建轮播图片存储目录失败", ex);
            }
        }

        //保存图片到Image文件夹并返回相对路径
        public static string SaveImage(string sourcePath)
        {
            if (string.IsNullOrEmpty(sourcePath))
            {
                throw new ImageProcessException("源图片路径不能为空");
            }
            
            try
            {
                //检查文件是否存在
                if (!File.Exists(sourcePath))
                {
                    throw new ImageProcessException($"找不到源图片文件: {sourcePath}");
                }
                
                //获取存储目录
                string imagesDir = GetImageDirectory();
                
                //生成唯一文件名
                string fileExt = Path.GetExtension(sourcePath);
                string fileName = Guid.NewGuid().ToString("N") + fileExt;
                string destPath = Path.Combine(imagesDir, fileName);
                
                //使用内存流方式复制文件，避免文件锁定问题
                using (var memoryStream = new MemoryStream())
                {
                    //先将源文件读入内存流
                    using (var fileStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read))
                    {
                        byte[] buffer = new byte[1024];
                        int bytesRead;
                        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            memoryStream.Write(buffer, 0, bytesRead);
                        }
                        memoryStream.Position = 0;
                    }
                    
                    //从内存流创建图片
                    using (var image = Image.FromStream(memoryStream))
                    {
                        //检查图片是否有效
                        if (image.Width <= 0 || image.Height <= 0)
                        {
                            throw new ImageProcessException("无效的图片文件");
                        }
                        
                        //保存为新文件
                        ImageFormat format = ImageFormat.Jpeg; //默认使用JPEG
                        
                        switch (fileExt.ToLower())
                        {
                            case ".png":
                                format = ImageFormat.Png;
                                break;
                            case ".gif":
                                format = ImageFormat.Gif;
                                break;
                            case ".bmp":
                                format = ImageFormat.Bmp;
                                break;
                        }
                        
                        image.Save(destPath, format);
                    }
                }
                
                //返回相对路径，用于存储到数据库
                return "Images/" + fileName;
            }
            catch (UnauthorizedAccessException ex)
            {
                throw new ImageProcessException($"没有权限访问图片文件: {sourcePath}", ex);
            }
            catch (SecurityException ex)
            {
                throw new ImageProcessException($"安全限制，无法访问图片文件: {sourcePath}", ex);
            }
            catch (FileNotFoundException ex)
            {
                throw new ImageProcessException($"找不到图片文件: {sourcePath}", ex);
            }
            catch (ArgumentException ex)
            {
                throw new ImageProcessException($"图片路径参数无效: {sourcePath}", ex);
            }
            catch (PathTooLongException ex)
            {
                throw new ImageProcessException("图片路径过长", ex);
            }
            catch (IOException ex)
            {
                throw new ImageProcessException($"保存图片时发生IO错误: {ex.Message}", ex);
            }
            catch (ImageProcessException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new ImageProcessException($"保存图片时发生未知错误: {ex.Message}", ex);
            }
        }

        //根据相对路径加载图片
        public static Image LoadImage(string relativeImagePath)
        {
            if (string.IsNullOrEmpty(relativeImagePath))
            {
                throw new ImageProcessException("图片路径不能为空");
            }

            try
            {
                //如果路径以Image/开头，自动转换为Images/
                if (relativeImagePath.StartsWith("Image/"))
                {
                    relativeImagePath = "Images/" + relativeImagePath.Substring(6);
                }
                
                //获取文件名
                string fileName = Path.GetFileName(relativeImagePath);
                
                //获取项目根目录下的Images文件夹
                string baseDir = AppDomain.CurrentDomain.BaseDirectory;
                string projectDir = baseDir;
                if (baseDir.Contains("\\bin\\"))
                {
                    projectDir = baseDir.Substring(0, baseDir.IndexOf("\\bin\\"));
                }
                
                //尝试从项目根目录的Images文件夹加载
                string projectImagesPath = Path.Combine(projectDir, "Images", fileName);
                if (File.Exists(projectImagesPath))
                {
                    using (var stream = new FileStream(projectImagesPath, FileMode.Open, FileAccess.Read))
                    {
                        return Image.FromStream(stream);
                    }
                }
                
                //如果项目根目录没有，尝试从bin目录加载
                string binImagesPath = Path.Combine(baseDir, "Images", fileName);
                if (File.Exists(binImagesPath))
                {
                    using (var stream = new FileStream(binImagesPath, FileMode.Open, FileAccess.Read))
                    {
                        return Image.FromStream(stream);
                    }
                }
                
                //如果还是找不到，尝试直接使用相对路径
                string fullPath = Path.Combine(baseDir, relativeImagePath);
                if (File.Exists(fullPath))
                {
                    using (var stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read))
                    {
                        return Image.FromStream(stream);
                    }
                }
                
                //所有尝试都失败，抛出异常
                throw new ImageProcessException($"找不到图片文件: {relativeImagePath}");
            }
            catch (UnauthorizedAccessException ex)
            {
                throw new ImageProcessException($"没有权限访问图片文件: {relativeImagePath}", ex);
            }
            catch (SecurityException ex)
            {
                throw new ImageProcessException($"安全限制，无法访问图片文件: {relativeImagePath}", ex);
            }
            catch (FileNotFoundException ex)
            {
                throw new ImageProcessException($"找不到图片文件: {relativeImagePath}", ex);
            }
            catch (IOException ex)
            {
                throw new ImageProcessException($"加载图片时发生IO错误: {ex.Message}", ex);
            }
            catch (ImageProcessException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new ImageProcessException($"加载图片时发生未知错误: {ex.Message}", ex);
            }
        }

        //缩放图片以适应指定的容器大小
        public static Rectangle GetScaledRectangle(Size imageSize, Size boxSize)
        {
            try
            {
                if (imageSize.Width <= 0 || imageSize.Height <= 0)
                {
                    throw new ImageProcessException("图片尺寸无效");
                }
                
                if (boxSize.Width <= 0 || boxSize.Height <= 0)
                {
                    throw new ImageProcessException("容器尺寸无效");
                }
                
                //计算缩放比例，保持图片原比例
                float ratio;
                if (imageSize.Width > imageSize.Height)
                {
                    ratio = (float)boxSize.Width / imageSize.Width;
                }
                else
                {
                    ratio = (float)boxSize.Height / imageSize.Height;
                }

                //计算新尺寸
                int newWidth = (int)(imageSize.Width * ratio);
                int newHeight = (int)(imageSize.Height * ratio);

                //计算居中位置
                int x = (boxSize.Width - newWidth) / 2;
                int y = (boxSize.Height - newHeight) / 2;

                return new Rectangle(x, y, newWidth, newHeight);
            }
            catch (ImageProcessException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new ImageProcessException("计算图片缩放尺寸时发生错误", ex);
            }
        }

        //保存图片到Images/Carousel文件夹并返回相对路径
        public static string SaveCarouselImage(string sourcePath)
        {
            if (string.IsNullOrEmpty(sourcePath))
            {
                throw new ImageProcessException("源图片路径不能为空");
            }
            
            try
            {
                //检查文件是否存在
                if (!File.Exists(sourcePath))
                {
                    throw new ImageProcessException($"找不到源图片文件: {sourcePath}");
                }
                
                //获取轮播图片存储目录
                string carouselDir = GetCarouselImageDirectory();
                
                //生成唯一文件名
                string fileExt = Path.GetExtension(sourcePath);
                string fileName = Guid.NewGuid().ToString("N") + fileExt;
                string destPath = Path.Combine(carouselDir, fileName);
                
                //使用内存流方式复制文件，避免文件锁定问题
                using (var memoryStream = new MemoryStream())
                {
                    //先将源文件读入内存流
                    using (var fileStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read))
                    {
                        byte[] buffer = new byte[1024];
                        int bytesRead;
                        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            memoryStream.Write(buffer, 0, bytesRead);
                        }
                        memoryStream.Position = 0;
                    }
                    
                    //从内存流创建图片
                    using (var image = Image.FromStream(memoryStream))
                    {
                        //检查图片是否有效
                        if (image.Width <= 0 || image.Height <= 0)
                        {
                            throw new ImageProcessException("无效的图片文件");
                        }
                        
                        //保存为新文件
                        ImageFormat format = ImageFormat.Jpeg; //默认使用JPEG
                        
                        switch (fileExt.ToLower())
                        {
                            case ".png":
                                format = ImageFormat.Png;
                                break;
                            case ".gif":
                                format = ImageFormat.Gif;
                                break;
                            case ".bmp":
                                format = ImageFormat.Bmp;
                                break;
                        }
                        
                        image.Save(destPath, format);
                    }
                }
                
                //返回相对路径，用于存储到数据库
                return "Images/Carousel/" + fileName;
            }
            catch (UnauthorizedAccessException ex)
            {
                throw new ImageProcessException($"没有权限访问图片文件: {sourcePath}", ex);
            }
            catch (SecurityException ex)
            {
                throw new ImageProcessException($"安全限制，无法访问图片文件: {sourcePath}", ex);
            }
            catch (FileNotFoundException ex)
            {
                throw new ImageProcessException($"找不到图片文件: {sourcePath}", ex);
            }
            catch (ArgumentException ex)
            {
                throw new ImageProcessException($"图片路径参数无效: {sourcePath}", ex);
            }
            catch (PathTooLongException ex)
            {
                throw new ImageProcessException("图片路径过长", ex);
            }
            catch (IOException ex)
            {
                throw new ImageProcessException($"保存图片时发生IO错误: {ex.Message}", ex);
            }
            catch (ImageProcessException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new ImageProcessException($"保存轮播图片时发生未知错误: {ex.Message}", ex);
            }
        }

        //加载轮播图片
        public static Image LoadCarouselImage(string relativeImagePath)
        {
            if (string.IsNullOrEmpty(relativeImagePath))
            {
                throw new ImageProcessException("图片路径不能为空");
            }

            try
            {
                //确保路径格式正确
                if (!relativeImagePath.Contains("Carousel"))
                {
                    //如果路径不包含Carousel，尝试常规方式加载
                    return LoadImage(relativeImagePath);
                }
                
                //获取文件名
                string fileName = Path.GetFileName(relativeImagePath);
                
                //获取项目根目录
                string baseDir = AppDomain.CurrentDomain.BaseDirectory;
                string projectDir = baseDir;
                if (baseDir.Contains("\\bin\\"))
                {
                    //回溯到项目根目录
                    projectDir = baseDir.Substring(0, baseDir.IndexOf("\\bin\\"));
                }
                
                //尝试从项目根目录的Images/Carousel文件夹加载
                string projectCarouselPath = Path.Combine(projectDir, "Images", "Carousel", fileName);
                if (File.Exists(projectCarouselPath))
                {
                    using (var stream = new FileStream(projectCarouselPath, FileMode.Open, FileAccess.Read))
                    {
                        return Image.FromStream(stream);
                    }
                }
                
                //如果项目根目录没有，尝试从bin目录加载
                string binCarouselPath = Path.Combine(baseDir, "Images", "Carousel", fileName);
                if (File.Exists(binCarouselPath))
                {
                    using (var stream = new FileStream(binCarouselPath, FileMode.Open, FileAccess.Read))
                    {
                        return Image.FromStream(stream);
                    }
                }
                
                //如果还是找不到，尝试直接使用相对路径
                string fullPath = Path.Combine(baseDir, relativeImagePath);
                if (File.Exists(fullPath))
                {
                    using (var stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read))
                    {
                        return Image.FromStream(stream);
                    }
                }
                
                //所有尝试都失败，抛出异常
                throw new ImageProcessException($"找不到轮播图片文件: {relativeImagePath}");
            }
            catch (UnauthorizedAccessException ex)
            {
                throw new ImageProcessException($"没有权限访问轮播图片文件: {relativeImagePath}", ex);
            }
            catch (SecurityException ex)
            {
                throw new ImageProcessException($"安全限制，无法访问轮播图片文件: {relativeImagePath}", ex);
            }
            catch (FileNotFoundException ex)
            {
                throw new ImageProcessException($"找不到轮播图片文件: {relativeImagePath}", ex);
            }
            catch (IOException ex)
            {
                throw new ImageProcessException($"加载轮播图片时发生IO错误: {ex.Message}", ex);
            }
            catch (ImageProcessException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new ImageProcessException($"加载轮播图片时发生未知错误: {ex.Message}", ex);
            }
        }
    }
}
